package chatserver;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Scanner;
import java.util.Vector;

public class ServerThread extends Thread
{
	private Vector<Chatter> clients=null;	//passed from Server mian thread
	private Vector<ChatRoom> chatRooms=null;
	private boolean stop=false;			//are we stop
	private boolean isStop=false;	//stop yet?
	/**
	 * 
	 * @return true if we are stopped
	 */
	public boolean isStop()
	{
		return isStop;
	}
	/**
	 * 
	 * @param clients the vector of clients socket that main thread accept
	 */
	public ServerThread(Vector<Chatter> clients, Vector<ChatRoom> chatRooms)
	{
		this.clients=clients;
		this.chatRooms=chatRooms;
	}
        private Chatter getChatter(Socket clientSocket)
        {
            for(int i=0;i<clients.size();i++)
            {
                if(clients.get(i).getSocket()==clientSocket)
                    return clients.get(i);
            }
            return null;
        }
        private ChatRoom getChatRoom(String roomName)
        {
            for(int i=0;i<this.chatRooms.size();i++)
            {
                if(chatRooms.get(i).getRoomName().equals(roomName))
                    return chatRooms.get(i);

            }
            return null;

        }
        public void getRoomList(PrintWriter out)
        {
            out.println("LISTROOM");
            out.println("START");
            System.out.println("START");
            for(int i=0;i<this.chatRooms.size();i++)
            {
                System.out.println(chatRooms.get(i).toString());
                out.println(chatRooms.get(i).toString());
            }
            out.println("END");
            System.out.println("END");
        }
        public void joinRoom(Socket clientSocket,String roomName, PrintWriter out,String tail)
        {
            Chatter client=getChatter(clientSocket);
            String[]result = tail.split(",");
            ChatRoom chatRoom;
            if(result.length>=2)
            {
                chatRoom=getChatRoom(roomName);
                if(chatRoom==null)
                {
                    System.out.println("Hacking!");
                    return;
                }
                chatRoom.setPassword(result[1]);
            }
            else
            {
                chatRoom=getChatRoom(roomName);
            }
            if(chatRoom==null)
            {
                System.out.println("Hacking!");
                return;
            }
            ChatRoom oldRoom=client.getChatRoom();
            chatRoom.addChatter(client);
            System.out.println("Chatter "+client.getNick()+" join room "+chatRoom.getRoomName());
            out.println("JOINROOM");
            out.println("START");
            System.out.println("START");
            Vector<Chatter> chatters=chatRoom.getChatters();

            for(int i=0;i<chatters.size();i++)
            {
                out.println(chatters.get(i).getNick());
                System.out.println(chatters.get(i).getNick());
                if(!chatters.get(i).getNick().equals(client.getNick()))
                {
                    //inform other about this chatter
                    try
                    {
                        PrintWriter clientOut=new PrintWriter(chatters.get(i).getSocket().getOutputStream());
                        System.out.println("Send NEWCHATTER to " + chatters.get(i).getNick());
                        clientOut.println("NEWCHATTER");
                        clientOut.println(client.getNick());
                        System.out.println(client.getNick());
                        clientOut.flush();
                    }catch(Exception e)
                    {
                        e.printStackTrace();;
                    }
                }
            }
            out.println("END");
            System.out.println("END");
            if(oldRoom!=null)
            {
                //inform all in old room that this client is leaving
                chatters=oldRoom.getChatters();
                for(int i=0;i<chatters.size();i++)
                {
                    try
                    {
                        PrintWriter clientOut=new PrintWriter(chatters.get(i).getSocket().getOutputStream());
                        clientOut.println("CHATTERLEAVE");
                        clientOut.println(client.getNick());
                        clientOut.flush();
                    }catch(Exception e)
                    {
                        e.printStackTrace();;
                    }
                }
            }
        }
        public void chat(String message, Socket clientSocket)
        {
            Chatter client=getChatter(clientSocket);
            ChatRoom chatRoom=getChatRoom(client.getChatRoom().getRoomName());
            Vector<Chatter> chatters=chatRoom.getChatters();
            for(int i=0;i<chatters.size();i++)
            {

                //inform other about this chatter
                try
                {
                    PrintWriter clientOut=new PrintWriter(chatters.get(i).getSocket().getOutputStream());
                    clientOut.println("CHAT");
                    clientOut.println(client.getNick()+":"+message);
                    clientOut.flush();
                }catch(Exception e)
                {
                    e.printStackTrace();;
                }
            }
        }
        public String login(String nickName, Socket clientSock)
        {
            int index=-1;
            for(int i=0;i<clients.size();i++)
            {
                if(clients.get(i).getSocket()==clientSock)
                    index=i;
                if(clients.get(i).getNick().equals(nickName))
                    return "ERR:nick name in use!";
            }
            clients.get(index).setNick(nickName);
            return "OK";
        }
	/**
	 * call to stop this thread
	 */
	public void end()
	{
		stop=true;
	}
	public void run()
	{
		while(!stop)	//while not stop
		{
			if(this.clients==null)	//if have no client to process, continue
			{
				try {
					Thread.sleep(100);	//politely give up CPU
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				continue;
			}
			Vector<Chatter> removeClients=new Vector<Chatter>();	//client to be removed
			Enumeration<Chatter> e = clients.elements();
			while( e.hasMoreElements() ){
				Socket clientSocket =e.nextElement().getSocket();
				try{
					if(clientSocket.isClosed() || clientSocket.isInputShutdown() || clientSocket.isOutputShutdown())	//this clietn is dead
					{
						removeClients.add(getChatter(clientSocket));	//mark it to be removed
					}
					else if(clientSocket.getInputStream().available()>0)	//have client data
					{
						Scanner in = new Scanner(clientSocket.getInputStream());
						PrintWriter out=new PrintWriter(clientSocket.getOutputStream());
						String line=in.nextLine();
						String[] tokens=line.split(":");	//split into tokens separated by spaces
						String command=tokens[0];	//the first token is the command
						if(command.equals("LISTROOM"))	//get client ip
						{
                                                    System.out.println("Get LISTROOM");
                                                    getRoomList(out);
						}
                                                else if(command.equals("JOINROOM"))
                                                {
                                                    
                                                    String roomName=tokens[1];
                                                    String roomTail = tokens[2];
                                                    System.out.println("Get JOINROOM "+roomName);
                                                    joinRoom(clientSocket,roomName,out,roomTail);
                                                }
                                                else if(command.equals("LOGIN"))
                                                {
                                                    String nickName=tokens[1];
                                                    String ret=login(nickName,clientSocket);
                                                    out.println(ret);
                                                }
                                                else if(command.equals("CHAT"))
                                                {
                                                    String message="";
                                                    for(int i=1;i<tokens.length;i++)
                                                    {
                                                        message+=tokens[i]+":";
                                                    }
                                                    message=message.substring(0,message.length()-1);
                                                    chat(message,clientSocket);
                                                }
                                                else if(command.equals("EXIT"))
                                                {
                                                    out.println("EXIT");
                                                    System.out.println("Got EXIT");
                                                    removeClients.add(getChatter(clientSocket));	//mark it to be removed
                                                }
						else	//other commands
						{
							out.println("Unknown command!");
						}
						out.flush();	//make sure client receive the data
					}
				}catch(Exception ex)
				{
					continue;
				}
			}
			//now, after finish looping the clients, we can start removing them
			for(int i=0;i<removeClients.size();i++)
			{
				try {
                                        Chatter chatter=removeClients.get(i);
                                        ChatRoom chatRoom=chatter.getChatRoom();
                                        if(chatRoom!=null)
                                        {
                                            chatRoom.removeChatter(chatter.getNick());
                                            Vector<Chatter> chatters=chatRoom.getChatters();
                                            for(int j=0;j<chatters.size();j++)
                                            {
                                                try
                                                {
                                                    PrintWriter clientOut=new PrintWriter(chatters.get(j).getSocket().getOutputStream());
                                                    clientOut.println("CHATTERLEAVE");
                                                    clientOut.println(chatter.getNick());
                                                    clientOut.flush();
                                                }catch(Exception ex)
                                                {
                                                    ex.printStackTrace();;
                                                }
                                            }
                                        }
					removeClients.get(i).getSocket().close();	//close connection
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				clients.remove(removeClients.get(i));//remove it from our monitor Vector
			}
			
		}
		isStop=true;	//oh, someone for me to stop
	}
}
